home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_195 / microemacs / src.zoo / basic.c < prev    next >
C/C++ Source or Header  |  1989-03-23  |  14KB  |  487 lines

  1. /*
  2.  * The routines in this file move the cursor around on the screen. They
  3.  * compute a new value for the cursor, then adjust ".". The display code
  4.  * always updates the cursor location, so only moves between lines, or
  5.  * functions that adjust the top line in the window and invalidate the
  6.  * framing, are hard.
  7.  */
  8. #include    <stdio.h>
  9. #include    "estruct.h"
  10. #include    "etype.h"
  11. #include    "edef.h"
  12. #include    "elang.h"
  13.  
  14. /*
  15.  * Move the cursor to the
  16.  * beginning of the current line.
  17.  * Trivial.
  18.  */
  19. PASCAL NEAR gotobol(f, n)
  20. {
  21.         curwp->w_doto  = 0;
  22.         return(TRUE);
  23. }
  24.  
  25. /*
  26.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  27.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  28.  * location. Error if you try and move out of the buffer. Set the flag if the
  29.  * line pointer for dot changes.
  30.  */
  31. PASCAL NEAR backchar(f, n)
  32. register int    n;
  33. {
  34.         register LINE   *lp;
  35.  
  36.         if (n < 0)
  37.                 return(forwchar(f, -n));
  38.         while (n--) {
  39.                 if (curwp->w_doto == 0) {
  40.                         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  41.                                 return(FALSE);
  42.                         curwp->w_dotp  = lp;
  43.                         curwp->w_doto  = llength(lp);
  44.                         curwp->w_flag |= WFMOVE;
  45.                 } else
  46.                         curwp->w_doto--;
  47.         }
  48.         return(TRUE);
  49. }
  50.  
  51. /*
  52.  * Move the cursor to the end of the current line. Trivial. No errors.
  53.  */
  54. PASCAL NEAR gotoeol(f, n)
  55. {
  56.         curwp->w_doto  = llength(curwp->w_dotp);
  57.         return(TRUE);
  58. }
  59.  
  60. /*
  61.  * Move the cursor forwards by "n" characters. If "n" is less than zero call
  62.  * "backchar" to actually do the move. Otherwise compute the new cursor
  63.  * location, and move ".". Error if you try and move off the end of the
  64.  * buffer. Set the flag if the line pointer for dot changes.
  65.  */
  66. PASCAL NEAR forwchar(f, n)
  67. register int    n;
  68. {
  69.         if (n < 0)
  70.                 return(backchar(f, -n));
  71.         while (n--) {
  72.                 if (curwp->w_doto == llength(curwp->w_dotp)) {
  73.                         if (curwp->w_dotp == curbp->b_linep)
  74.                                 return(FALSE);
  75.                         curwp->w_dotp  = lforw(curwp->w_dotp);
  76.                         curwp->w_doto  = 0;
  77.                         curwp->w_flag |= WFMOVE;
  78.                 } else
  79.                         curwp->w_doto++;
  80.         }
  81.         return(TRUE);
  82. }
  83.  
  84. PASCAL NEAR gotoline(f, n)    /* move to a particular line.
  85.                argument (n) must be a positive integer for
  86.                this to actually do anything        */
  87.  
  88. {
  89.     register int status;    /* status return */
  90.     char arg[NSTRING];    /* buffer to hold argument */
  91.  
  92.     /* get an argument if one doesnt exist */
  93.     if (f == FALSE) {
  94.         if ((status = mlreply(TEXT7, arg, NSTRING)) != TRUE) {
  95. /*                                    "Line to GOTO: " */
  96.             mlwrite(TEXT8);
  97. /*                              "[Aborted]" */
  98.             return(status);
  99.         }
  100.         n = asc_int(arg);
  101.     }
  102.  
  103.     if (n < 1)        /* if a bogus argument...then leave */
  104.         return(FALSE);
  105.  
  106.     /* first, we go to the start of the buffer */
  107.         curwp->w_dotp  = lforw(curbp->b_linep);
  108.         curwp->w_doto  = 0;
  109.     return(forwline(f, n-1));
  110. }
  111.  
  112. /*
  113.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  114.  * considered to be hard motion; it really isn't if the original value of dot
  115.  * is the same as the new value of dot. Normally bound to "M-<".
  116.  */
  117. PASCAL NEAR gotobob(f, n)
  118. {
  119.         curwp->w_dotp  = lforw(curbp->b_linep);
  120.         curwp->w_doto  = 0;
  121.         curwp->w_flag |= WFHARD;
  122.         return(TRUE);
  123. }
  124.  
  125. /*
  126.  * Move to the end of the buffer. Dot is always put at the end of the file
  127.  * (ZJ). The standard screen code does most of the hard parts of update.
  128.  * Bound to "M->".
  129.  */
  130. PASCAL NEAR gotoeob(f, n)
  131. {
  132.         curwp->w_dotp  = curbp->b_linep;
  133.         curwp->w_doto  = 0;
  134.         curwp->w_flag |= WFHARD;
  135.         return(TRUE);
  136. }
  137.  
  138. /*
  139.  * Move forward by full lines. If the number of lines to move is less than
  140.  * zero, call the backward line function to actually do it. The last command
  141.  * controls how the goal column is set. Bound to "C-N". No errors are
  142.  * possible.
  143.  */
  144. PASCAL NEAR forwline(f, n)
  145. {
  146.         register LINE   *dlp;
  147.  
  148.         if (n < 0)
  149.                 return(backline(f, -n));
  150.  
  151.     /* if we are on the last line as we start....fail the command */
  152.     if (curwp->w_dotp == curbp->b_linep)
  153.         return(FALSE);
  154.  
  155.     /* if the last command was not note a line move,
  156.        reset the goal column */
  157.         if ((lastflag&CFCPCN) == 0)
  158.                 curgoal = getccol(FALSE);
  159.  
  160.     /* flag this command as a line move */
  161.         thisflag |= CFCPCN;
  162.  
  163.     /* and move the point down */
  164.         dlp = curwp->w_dotp;
  165.         while (n-- && dlp!=curbp->b_linep)
  166.                 dlp = lforw(dlp);
  167.  
  168.     /* reseting the current position */
  169.         curwp->w_dotp  = dlp;
  170.         curwp->w_doto  = getgoal(dlp);
  171.         curwp->w_flag |= WFMOVE;
  172.         return(TRUE);
  173. }
  174.  
  175. /*
  176.  * This function is like "forwline", but goes backwards. The scheme is exactly
  177.  * the same. Check for arguments that are less than zero and call your
  178.  * alternate. Figure out the new line and call "movedot" to perform the
  179.  * motion. No errors are possible. Bound to "C-P".
  180.  */
  181. PASCAL NEAR backline(f, n)
  182. {
  183.         register LINE   *dlp;
  184.  
  185.         if (n < 0)
  186.                 return(forwline(f, -n));
  187.  
  188.  
  189.     /* if we are on the last line as we start....fail the command */
  190.     if (lback(curwp->w_dotp) == curbp->b_linep)
  191.         return(FALSE);
  192.  
  193.     /* if the last command was not note a line move,
  194.        reset the goal column */
  195.         if ((lastflag&CFCPCN) == 0)
  196.                 curgoal = getccol(FALSE);
  197.  
  198.     /* flag this command as a line move */
  199.         thisflag |= CFCPCN;
  200.  
  201.     /* and move the point up */
  202.         dlp = curwp->w_dotp;
  203.         while (n-- && lback(dlp)!=curbp->b_linep)
  204.                 dlp = lback(dlp);
  205.  
  206.     /* reseting the current position */
  207.         curwp->w_dotp  = dlp;
  208.         curwp->w_doto  = getgoal(dlp);
  209.         curwp->w_flag |= WFMOVE;
  210.         return(TRUE);
  211. }
  212.  
  213. #if    WORDPRO
  214. PASCAL NEAR gotobop(f, n) /* go back to the beginning of the current paragraph
  215.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  216.            combination to delimit the beginning of a paragraph    */
  217.  
  218. int f, n;    /* default Flag & Numeric argument */
  219.  
  220. {
  221.     register int suc;    /* success of last backchar */
  222.  
  223.     if (n < 0)    /* the other way...*/
  224.         return(gotoeop(f, -n));
  225.  
  226.     while (n-- > 0) {    /* for each one asked for */
  227.  
  228.         /* first scan back until we are in a word */
  229.         suc = backchar(FALSE, 1);
  230.         while (!inword() && suc)
  231.             suc = backchar(FALSE, 1);
  232.         curwp->w_doto = 0;    /* and go to the B-O-Line */
  233.  
  234.         /* and scan back until we hit a <NL><NL> or <NL><TAB>
  235.            or a <NL><SPACE>                    */
  236.         while (lback(curwp->w_dotp) != curbp->b_linep)
  237.             if (llength(curwp->w_dotp) != 0 &&
  238.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  239.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  240.                 curwp->w_dotp = lback(curwp->w_dotp);
  241.             else
  242.                 break;
  243.  
  244.         /* and then forward until we are in a word */
  245.         suc = forwchar(FALSE, 1);
  246.         while (suc && !inword())
  247.             suc = forwchar(FALSE, 1);
  248.     }
  249.     curwp->w_flag |= WFMOVE;    /* force screen update */
  250.     return(TRUE);
  251. }
  252.  
  253. PASCAL NEAR gotoeop(f, n) /* go forword to the end of the current paragraph
  254.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  255.            combination to delimit the beginning of a paragraph    */
  256.  
  257. int f, n;    /* default Flag & Numeric argument */
  258.  
  259. {
  260.     register int suc;    /* success of last backchar */
  261.  
  262.     if (n < 0)    /* the other way...*/
  263.         return(gotobop(f, -n));
  264.  
  265.     while (n-- > 0) {    /* for each one asked for */
  266.  
  267.         /* first scan forward until we are in a word */
  268.         suc = forwchar(FALSE, 1);
  269.         while (!inword() && suc)
  270.             suc = forwchar(FALSE, 1);
  271.         curwp->w_doto = 0;    /* and go to the B-O-Line */
  272.         if (suc)    /* of next line if not at EOF */
  273.             curwp->w_dotp = lforw(curwp->w_dotp);
  274.  
  275.         /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  276.            or a <NL><SPACE>                    */
  277.         while (curwp->w_dotp != curbp->b_linep) {
  278.             if (llength(curwp->w_dotp) != 0 &&
  279.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  280.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  281.                 curwp->w_dotp = lforw(curwp->w_dotp);
  282.             else
  283.                 break;
  284.         }
  285.  
  286.         /* and then backward until we are in a word */
  287.         suc = backchar(FALSE, 1);
  288.         while (suc && !inword()) {
  289.             suc = backchar(FALSE, 1);
  290.         }
  291.         curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  292.     }
  293.     curwp->w_flag |= WFMOVE;    /* force screen update */
  294.     return(TRUE);
  295. }
  296. #endif
  297.  
  298. /*
  299.  * This routine, given a pointer to a LINE, and the current cursor goal
  300.  * column, return the best choice for the offset. The offset is returned.
  301.  * Used by "C-N" and "C-P".
  302.  */
  303. PASCAL NEAR getgoal(dlp)
  304. register LINE   *dlp;
  305. {
  306.         register int    c;
  307.         register int    col;
  308.         register int    newcol;
  309.         register int    dbo;
  310.  
  311.         col = 0;
  312.         dbo = 0;
  313.         while (dbo != llength(dlp)) {
  314.                 c = lgetc(dlp, dbo);
  315.                 newcol = col;
  316.                 if (c == '\t')
  317.             newcol += -(newcol % tabsize) + (tabsize - 1);
  318.                 else if (c<0x20 || c==0x7F)
  319.                         ++newcol;
  320.                 ++newcol;
  321.                 if (newcol > curgoal)
  322.                         break;
  323.                 col = newcol;
  324.                 ++dbo;
  325.         }
  326.         return(dbo);
  327. }
  328.  
  329. /*
  330.  * Scroll forward by a specified number of lines, or by a full page if no
  331.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  332.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  333.  * this zaps the top line in the display window, we have to do a hard update.
  334.  */
  335. PASCAL NEAR forwpage(f, n)
  336. register int    n;
  337. {
  338.         register LINE   *lp;
  339.  
  340.         if (f == FALSE) {
  341.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  342.                 if (n <= 0)                     /* Forget the overlap   */
  343.                         n = 1;                  /* if tiny window.      */
  344.         } else if (n < 0)
  345.                 return(backpage(f, -n));
  346. #if     CVMVAS
  347.         else                                    /* Convert from pages   */
  348.                 n *= curwp->w_ntrows;           /* to lines.            */
  349. #endif
  350.         lp = curwp->w_linep;
  351.         while (n-- && lp!=curbp->b_linep)
  352.                 lp = lforw(lp);
  353.         curwp->w_linep = lp;
  354.         curwp->w_dotp  = lp;
  355.         curwp->w_doto  = 0;
  356.         curwp->w_flag |= WFHARD;
  357.         return(TRUE);
  358. }
  359.  
  360. /*
  361.  * This command is like "forwpage", but it goes backwards. The "2", like
  362.  * above, is the overlap between the two windows. The value is from the ITS
  363.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  364.  * reason.
  365.  */
  366. PASCAL NEAR backpage(f, n)
  367.  
  368. register int f;
  369. register int n;
  370.  
  371. {
  372.         register LINE   *lp;
  373.  
  374.         if (f == FALSE) {
  375.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  376.                 if (n <= 0)                     /* Don't blow up if the */
  377.                         n = 1;                  /* window is tiny.      */
  378.         } else if (n < 0)
  379.                 return(forwpage(f, -n));
  380. #if     CVMVAS
  381.         else                                    /* Convert from pages   */
  382.                 n *= curwp->w_ntrows;           /* to lines.            */
  383. #endif
  384.         lp = curwp->w_linep;
  385.         while (n-- && lback(lp)!=curbp->b_linep)
  386.                 lp = lback(lp);
  387.         curwp->w_linep = lp;
  388.         curwp->w_dotp  = lp;
  389.         curwp->w_doto  = 0;
  390.         curwp->w_flag |= WFHARD;
  391.         return(TRUE);
  392. }
  393.  
  394. /*
  395.  * Set the mark in the current window to the value of "." in the window. No
  396.  * errors are possible. Bound to "M-.".
  397.  */
  398. PASCAL NEAR setmark(f, n)
  399. {
  400.     /* make sure it is in range */
  401.     if (f == FALSE)
  402.         n = 0;
  403.     n %= NMARKS;
  404.  
  405.         curwp->w_markp[n] = curwp->w_dotp;
  406.         curwp->w_marko[n] = curwp->w_doto;
  407.         mlwrite(TEXT9, n);
  408. /*              "[Mark %d set]" */
  409.         return(TRUE);
  410. }
  411.  
  412. /*
  413.  * Remove the mark in the current window.
  414.  * Bound to ^X <space> 
  415.  */
  416. PASCAL NEAR remmark(f, n)
  417. {
  418.     /* make sure it is in range */
  419.     if (f == FALSE)
  420.         n = 0;
  421.     n %= NMARKS;
  422.  
  423.         curwp->w_markp[n] = NULL;
  424.         curwp->w_marko[n] = 0;
  425.         mlwrite(TEXT10, n);
  426. /*              "[Mark %d removed]" */
  427.         return(TRUE);
  428. }
  429.  
  430. /*
  431.  * Swap the values of "." and "mark" in the current window. This is pretty
  432.  * easy, bacause all of the hard work gets done by the standard routine
  433.  * that moves the mark about. The only possible error is "no mark". Bound to
  434.  * "C-X C-X".
  435.  */
  436. PASCAL NEAR swapmark(f, n)
  437. {
  438.         register LINE   *odotp;
  439.         register int    odoto;
  440.  
  441.     /* make sure it is in range */
  442.     if (f == FALSE)
  443.         n = 0;
  444.     n %= NMARKS;
  445.  
  446.         if (curwp->w_markp[n] == NULL) {
  447.                 mlwrite(TEXT11, n);
  448. /*                      "No mark %d in this window" */
  449.                 return(FALSE);
  450.         }
  451.         odotp = curwp->w_dotp;
  452.         odoto = curwp->w_doto;
  453.         curwp->w_dotp  = curwp->w_markp[n];
  454.         curwp->w_doto  = curwp->w_marko[n];
  455.         curwp->w_markp[n] = odotp;
  456.         curwp->w_marko[n] = odoto;
  457.         curwp->w_flag |= WFMOVE;
  458.         return(TRUE);
  459. }
  460.  
  461. /*
  462.  * Goto a mark in the current window. This is pretty easy, bacause all of
  463.  * the hard work gets done by the standard routine that moves the mark
  464.  * about. The only possible error is "no mark". Bound to "M-^G".
  465.  */
  466. PASCAL NEAR gotomark(f, n)
  467.  
  468. int f, n;    /* default and nemeric args */
  469.  
  470. {
  471.     /* make sure it is in range */
  472.     if (f == FALSE)
  473.         n = 0;
  474.     n %= NMARKS;
  475.  
  476.         if (curwp->w_markp[n] == NULL) {
  477.                 mlwrite(TEXT11, n);
  478. /*                      "No mark %d in this window" */
  479.                 return(FALSE);
  480.         }
  481.         curwp->w_dotp  = curwp->w_markp[n];
  482.         curwp->w_doto  = curwp->w_marko[n];
  483.         curwp->w_flag |= WFMOVE;
  484.         return(TRUE);
  485. }
  486.  
  487.